package com.cloud.common.magic_init.handler;

import com.cloud.common.configure.TransmittableHolder;
import com.cloud.common.constants.GlobalConstants;
import com.cloud.common.domain.Result;
import com.cloud.domain.LoginUser;
import com.cloud.entity.AuthBody;
import com.cloud.exception.CustomException;
import com.cloud.exception.LoginException;
import com.cloud.service.FeignSecurityService;
import com.cloud.service.RedisService;
import com.cloud.utils.ToolUtils;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.ssssssss.magicapi.core.context.RequestEntity;
import org.ssssssss.magicapi.core.interceptor.RequestInterceptor;
import org.ssssssss.magicapi.core.model.ApiInfo;
import org.ssssssss.magicapi.core.model.Options;
import org.ssssssss.magicapi.core.model.Parameter;
import org.ssssssss.magicapi.core.servlet.MagicHttpServletRequest;
import org.ssssssss.magicapi.core.servlet.MagicHttpServletResponse;
import org.ssssssss.script.MagicScriptContext;

import java.util.concurrent.TimeUnit;

/**
 * Magic-api 鉴权配置
 *
 * @author yzj
 */
@Component
public class MagicRequestInterceptor implements RequestInterceptor {

    @Resource
    private FeignSecurityService feignSecurityService;

    @Resource
    private RedisService redisService;

    @Override
    public Object preHandle(ApiInfo info, MagicScriptContext context,
                            MagicHttpServletRequest request, MagicHttpServletResponse response) {
        // 判断Header中是否开启Redis缓存标识
        Object value = updateMagicHeader(info, GlobalConstants.openRedisHeader, null);
        if (ObjectUtils.isNotEmpty(value)) {
            return Result.success("查询成功", value);
        }
        // 获取Magic-api 接口中配置的权限字符
        String permission = info.getOptionValue(Options.PERMISSION);
        if (StringUtils.isNotEmpty(permission)) {
            String sysCode = request.getHeader(GlobalConstants.appTokenHeader);
            if (StringUtils.isEmpty(sysCode)) {
                return Result.message(LoginException.TOKEN_IS_EMPTY.getCode(),
                        LoginException.TOKEN_IS_EMPTY.getMessage());
            }
            // 获取登录用户信息
            TransmittableHolder.setUserId(getRequestHeader(request, GlobalConstants.userId));
            TransmittableHolder.setUserName(getRequestHeader(request, GlobalConstants.userName));
            TransmittableHolder.setDeptId(getRequestHeader(request, GlobalConstants.deptId));
            String tokenKey = getRequestHeader(request, GlobalConstants.tokenKey);
            TransmittableHolder.setTokenKey(tokenKey);
            // 接口配置了Token需要登录
            AuthBody authBody = new AuthBody();
            authBody.setSysCode(sysCode);
            authBody.setTokenKey(tokenKey);
            LoginUser loginUser = feignSecurityService.getLoginUser(authBody).getData();
            if (ObjectUtils.isEmpty(loginUser)) {
                return Result.message(LoginException.USER_NO_LOGIN_INVALID.getCode(),
                        LoginException.USER_NO_LOGIN_INVALID.getMessage());
            }
            loginUser.setSysCode(sysCode);
            TransmittableHolder.setLoginUser(loginUser);
            if (ObjectUtils.isNotEmpty(loginUser.getUserProject())) {
                if (loginUser.getUserProject().getPermissions().contains(permission)) {
                    return Result.message(LoginException.USER_NO_AUTHORITY.getCode(),
                            LoginException.USER_NO_AUTHORITY.getMsg());
                }
            }
        }
        return null;
    }

    @Override
    public Object postHandle(ApiInfo info, MagicScriptContext context, Object value,
                             MagicHttpServletRequest request, MagicHttpServletResponse response) {
        updateMagicHeader(info, GlobalConstants.openRedisHeader, value);
        return Result.success("查询成功", value);
    }

    @Override
    public void afterCompletion(RequestEntity requestEntity, Object returnValue, Throwable throwable) {
        // 移除 TransmittableThreadLocal对象
        TransmittableHolder.remove();
    }

    // 设置Http请求头
    private static String getRequestHeader(MagicHttpServletRequest request, String name) {
        String reqName = request.getHeader(name);
        if (StringUtils.isNotEmpty(reqName)) {
            return ToolUtils.httpDecoder(reqName);
        } else {
            throw new CustomException(LoginException.USER_NO_LOGIN_INVALID.getCode(),
                    LoginException.USER_NO_LOGIN_INVALID.getMessage());
        }
    }

    /**
     * 检验/更新结果缓存信息
     */
    private Object updateMagicHeader(ApiInfo info, String key, Object value) {
        if (ObjectUtils.isNotEmpty(info.getParameters())) {
            for (Parameter param : info.getParameters()) {
                if (param.getName().equals(key)) {
                    String nameValue = GlobalConstants.magicApiRedis + param.getValue();
                    if (redisService.keyIsExists(nameValue)) {
                        return redisService.get(nameValue);
                    }
                    // 缓存结果不存在,设置Redis缓存15分钟
                    if (ObjectUtils.isNotEmpty(value)) {
                        redisService.set(nameValue, value, GlobalConstants.openExpiration, TimeUnit.MINUTES);
                        return value;
                    }
                }
            }
        }
        return null;
    }

}
